/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package compiler.grammar;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author meemo
 */
public class Grammar
{
    //~ Instance fields --------------------------------------------------------

    private final ArrayList<NonTerminal> nonTerminals;
    private final ArrayList<Terminal>    terminals;
    private final Map<String, Symbol>    map = new HashMap<String, Symbol>();
    private final NonTerminal            startNonTerminal;

    //~ Constructors -----------------------------------------------------------

    public Grammar(ArrayList<Terminal> terminals, ArrayList<NonTerminal> nonTerminals)
    {
        startNonTerminal  = nonTerminals.get(0);
        this.terminals    = terminals;
        this.nonTerminals = nonTerminals;

        for (Terminal t : terminals)
        {
            map.put(t.getName(), t);
        }

        for (NonTerminal nt : nonTerminals)
        {
            map.put(nt.getName(), nt);
        }

        resolveReferences(nonTerminals);

        // epsilon is a special symbol terminal to be used only with first sets to indicated
        // nullability of the rule
        // instead we sue rule.nullable
    }

    //~ Methods ----------------------------------------------------------------

    public Map<String, Symbol> getMap()
    {
        return map;
    }

    public ArrayList<NonTerminal> getNonTerminals()
    {
        return nonTerminals;
    }

    public NonTerminal getStartNonTerminal()
    {
        return startNonTerminal;
    }

    public ArrayList<Terminal> getTerminals()
    {
        return terminals;
    }

    private void resolveReferences(ArrayList<NonTerminal> nonTerminals) throws IllegalArgumentException
    {
        boolean error = false;

        for (NonTerminal nt : nonTerminals)
        {
            for (Production prod : nt.getProductions())
            {
                boolean result = prod.resolveBody(map);
                error = error || result;
            }
        }

        if (error)
        {
            throw new IllegalArgumentException("Can't continue with the faulty grammar " + "(grammar using undeclared IDs)");
        }
    }
}
